/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.statemachine.editpart;

import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.XYLayout;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.DragTracker;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;
import org.eclipse.gef.tools.CellEditorLocator;
import org.eclipse.gef.tools.DirectEditManager;
import org.eclipse.ui.views.properties.IPropertySource;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.ElementImport;
import org.eclipse.uml2.uml.Region;

import com.cea.papyrus.core.directedit.ILabelControler;
import com.cea.papyrus.core.directedit.LabelCellEditorLocator;
import com.cea.papyrus.core.directedit.LabelControler;
import com.cea.papyrus.core.directedit.LabelDirectEditManager;
import com.cea.papyrus.core.directedit.PropertyAccessor;
import com.cea.papyrus.core.editor.ModelManager;
import com.cea.papyrus.core.editpart.ContainerWithSemanticEditPart;
import com.cea.papyrus.core.editpart.DimensionAdaptationEditPolicy;
import com.cea.papyrus.core.ui.properties.advanced.EObjectPropertySource;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.diagram.statemachine.figure.RegionFigure;
import com.cea.papyrus.diagram.statemachine.helper.NodeRegionHelper.Zone;
import com.cea.papyrus.diagraminterchange2.di2.Diagram;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;
import com.cea.papyrus.diagraminterchange2.di2.Property;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;

/**
 * Controler for Region in state machine diagrams.
 * 
 * @author David Servat
 * @since 29 jan. 07
 */
public class RegionEditPart extends ContainerWithSemanticEditPart{

	/**
	 * The channel.
	 */
	private int channel = 501;

	/**
	 * Manager for editing classname.
	 */
	private DirectEditManager manager;

	/** The DragTracker associated to the EditPart. */
	private DragTracker tracker = null;
	
	
	/**
	 * The constructor.
	 * 
	 * @param graphNode the GraphNode to be managed
	 * @param modelManager the associated ModelManager
	 */
	public RegionEditPart(GraphNode graphNode, ModelManager modelManager){
		super(graphNode, modelManager);

		Debug.debug(this,"call RegionEditPart(GraphNode graphnode, ModelManager modelManager)",channel);
	}

	/**
	 * This method is overriden to store the DragTracker locally.
	 * 
	 * @param request the associated Request
	 * 
	 * @return the DragTracker created by the superclass
	 */
	@Override
	public DragTracker getDragTracker(Request request){
		tracker = new RegionDragTracker(this);
		return tracker;
	}
	
	/**
	 * This method provides access to the RegionDragTracker if any or returns null.
	 * 
	 *  @return the RegionDragTracker
	 */
	public RegionDragTracker getRegionDragTracker(){
		if((tracker != null) && (tracker instanceof RegionDragTracker))
			return (RegionDragTracker)tracker;
		return null;
	}
	
	/**
	 * Specific edit policy installation.
	 * 
	 * @see com.cea.papyrus.common.editpart.ContainerWithSemanticEditPart#createEditPolicies()
	 */
	@Override
	protected void createEditPolicies(){
		super.createEditPolicies();
		installEditPolicy(EditPolicy.LAYOUT_ROLE, new StateMachineLayoutEditPolicy((XYLayout) getContentPane().getLayoutManager()));
		//manage suppression of this element
		installEditPolicy(EditPolicy.COMPONENT_ROLE, new RegionEditPolicy(modelManager));
		// AdaptDimensionEditPolicy
        installEditPolicy(DimensionAdaptationEditPolicy.DIMENSION_ADAPTATION, new ContainerDimensionAdaptationEditPolicy());
	}


	/**
	 * Calls for the appropriate figure associated to the element.
	 * 
	 * @return 
	 * 
	 * @see com.cea.papyrus.common.editpart.GraphNodeWithSemanticEditPart#createFigure()
	 */
	@Override
	protected IFigure createFigure(){
		return new RegionFigure();
	}


	/**
	 * Returns the associated UML element.
	 * 
	 * @see com.cea.papyrus.common.editpart.GraphNodeWithSemanticEditPart#getUmlElement()
	 */
	@Override
	public Region getUmlElement(){
		Element e = ((Uml1SemanticModelBridge)getGraphNode().getSemanticModel()).getElement();
        // Case of element import
        if(e instanceof ElementImport)
        	return (Region)((ElementImport)e).getImportedElement();
		return (Region)e;
	}

	/**
	 * This method is called whenever graphical changes need to be performed.
	 * The subtlety here is to check whther the region has bottom or right neighbours to change 
	 * some flags passed on the RegionFigure so as to paint a dash border.
	 * 
	 * @see org.eclipse.gef.editparts.AbstractEditPart#refreshVisuals()
	 */
	@Override
	protected void refreshVisuals(){
		Dimension size = getGraphNode().getSize();
		Point p = getGraphNode().getPosition();
		Rectangle r = new Rectangle(p, size);
		RegionFigure f = (RegionFigure) getFigure();

		//check for the region zone
		String kind = ((Property)getGraphNode().getProperty("zone")).getValue();
		//check the neighbours if any and change the corresponding flags in the figure
		if(Zone.hasRightNeighbours(kind))
			f.setDisplayRightBorder(true);
		else
			f.setDisplayRightBorder(false);
		if(Zone.hasBottomNeighbours(kind))
			f.setDisplayBottomBorder(true);
		else
			f.setDisplayBottomBorder(false);

		f.setName(getUmlElement().getName());
		//set colors
		f.refreshColors(getGraphNode());

//		//look for list of stereotypes
//		EList stereotypeList = getUmlElement().getAppliedStereotypes();
//		String stereotypes = "";
//		for(int i = 0; i < stereotypeList.size(); i++){
//			String name = ((Stereotype)stereotypeList.get(i)).getName();
//			stereotypes = stereotypes + name.substring(0, 1).toLowerCase() + name.substring(1, name.length()) + ", ";
//		}
//		if(stereotypes != ""){// stereotype exists
//			stereotypes = stereotypes.substring(0, stereotypes.length() - 2);
//			f.setStereotypes(stereotypes);
//		} 
//		else{
//			f.setStereotypes(null);
//		}


		//look for list of stereotypes
		f.refreshPresentation(getPresentation(), getUmlElement(), getGraphNode());
		com.cea.papyrus.umlutils.Element currentElement = new com.cea.papyrus.umlutils.Element(getUmlElement());
		boolean hasIcon  = currentElement.hasIcon();
		boolean hasShape = currentElement.hasShape();

		f.refreshStereotypes(f.stereotypesLabel(this), getPresentation(), hasIcon, hasShape);

		//qualifiedName
		GraphNode gp = (GraphNode) getGraphNode().getContainer();
		Element graphicalumlParent = null;
		if(gp != null){
			if(gp instanceof Diagram){
				if(((Diagram)gp).getOwner() != null){
					graphicalumlParent = ((Uml1SemanticModelBridge)((Diagram)gp).getOwner()).getElement();
				}
			} 
			else{
				if(gp.getSemanticModel() != null){
					graphicalumlParent = ((Uml1SemanticModelBridge)gp.getSemanticModel()).getElement();
				}
			}
		}

		if(graphicalumlParent != null){
			if (!(graphicalumlParent.equals(getUmlElement().getOwner()))){
				f.setQualifiedName(getUmlElement().getQualifiedName());
			}
		}

		((GraphicalEditPart) getParent()).setLayoutConstraint(this, f, r);
	}

	/**
	 * 
	 * 
	 * @return 
	 * 
	 * @see com.ibm.itso.sal330r.gefdemo.edit.NetworkElementEditPart#getPropertySource()
	 */
	@Override
	protected IPropertySource getPropertySource(){
		if (propertySource == null) {
			propertySource = new EObjectPropertySource(this.getUmlElement());
		}
		return propertySource;

	}

	/**
	 * Returns the Figure of this as a PackageFigure.
	 * 
	 * @return PackageFigure of this.
	 */
	protected RegionFigure getPackageBoardFigure(){
		return (RegionFigure) getFigure();
	}

	/**
	 * 
	 * 
	 * @return 
	 * 
	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#getContentPane()
	 */
	@Override
	public IFigure getContentPane(){
		return getPackageBoardFigure().getContentsPane();
	}

	/**
	 * Returns the Name Label of this edit part.
	 * 
	 * @return Label
	 */
	protected Label getNameLabel(){
		RegionFigure fig = (RegionFigure)getFigure();
		return fig.getNameLabel();
	}

	/**
	 * Init the label direct edit manager.
	 * This method should be called when a Direct Edit request is performed.
	 */
	protected void initLabelEditManager(){
		if(manager == null){
			//locator for the cell editor (on the name label)
			CellEditorLocator locator = new LabelCellEditorLocator(getNameLabel());

			//defining how properties are modified in the model
			PropertyAccessor accessor = new PropertyAccessor(){
				public String getPropertyName(){
					return "Name";
				}
				public String getValue(){
					return getUmlElement().getName();
				}
				public void setValue(String value){
					getUmlElement().setName(value);  
				}
			};
			//defines the controler: link between model and view
			ILabelControler labelControler = new LabelControler(getNameLabel(), accessor);

			//creates the editing manager.
			manager = new LabelDirectEditManager(this, locator, labelControler);
		}
	}

	/**
	 * the direct edit mechanism requires the edit part to handle the direct edit
	 * request.
	 * 
	 * @param req the request that called the direct edit.
	 */
	public void performDirectEdit(Request req){
//		initLabelEditManager();
//		manager.show();
	}

	/**
	 * 
	 * 
	 * @param request 
	 * 
	 * @see org.eclipse.gef.editparts.AbstractEditPart#performRequest(org.eclipse.gef.Request)
	 */
	@Override
	public void performRequest(Request request){
		if(request.getType() == RequestConstants.REQ_DIRECT_EDIT){
			performDirectEdit(request);
		}
	}
}
